package com.xia.juan.work.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.PathNotFoundException;
import com.xia.juan.work.domain.ExcelDataEntity;
import com.xia.juan.work.domain.FieldMappingEntity;
import com.xia.juan.work.enums.FileTypeEnum;
import com.xia.juan.work.service.DataCompareService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * @author wang
 */
@Slf4j
@Service
public class DataCompareServiceImpl implements DataCompareService {

    @Value("${xiajuan.root-path}")
    private String rootPath;

    private String excelFileName;

    private String txtFileName;

    @Override
    public List<String> scoreReview(List<FieldMappingEntity> fieldMappingEntityList,
                                    String sheetName)
            throws IOException {
        Assert.notEmpty(fieldMappingEntityList, "请先配置字段映射关系");
        // 读取文件内容
        Map<String, Object> studentIdToObjectMap = readTxtFile();
        List<ExcelDataEntity> excelDataEntities = readExcelFile(sheetName);
        Assert.equals(studentIdToObjectMap.size(), excelDataEntities.size(), "excel文件中的学生数量与系统中的不一致");
        List<String> errorInfos = new ArrayList<>(excelDataEntities.size());
        for (ExcelDataEntity excelDataEntity : excelDataEntities) {
            // 逐个比较
            Object studentInfoObject = studentIdToObjectMap.get(excelDataEntity.getStudentNumber());
            Assert.notNull(studentInfoObject, "系统中学号" + excelDataEntity.getStudentNumber() + "不存在");
            String[] excelRowValueArray = excelDataEntity.convertValueToArray();
            for (FieldMappingEntity fieldMappingEntity : fieldMappingEntityList) {
                String excelColumnValue = excelRowValueArray[fieldMappingEntity.getExcelColumnIndex()];
                Object jsonValue;
                try {
                    jsonValue = JsonPath.read(studentInfoObject, fieldMappingEntity.getJsonFeildNameEnum().getJsonPath());
                } catch (PathNotFoundException e) {
                    jsonValue = "0";
                }
                if (Objects.isNull(jsonValue) && !Objects.isNull(excelColumnValue)) {
                    errorInfos.add("学生 [" + excelDataEntity.getStudentName() + "] 的 [" + fieldMappingEntity.getJsonFeildNameEnum().getDesc() +
                            "] 有误，请检查，其学号为 [" + excelDataEntity.getStudentNumber() + "]");
                }
                if (Objects.isNull(jsonValue) && Objects.isNull(excelColumnValue)) {
                    continue;
                }
                if (!StrUtil.equals(excelColumnValue, jsonValue.toString())) {
                    errorInfos.add("学生 [" + excelDataEntity.getStudentName() + "] 的 [" + fieldMappingEntity.getJsonFeildNameEnum().getDesc() +
                            "] 有误，请检查，其学号为 [" + excelDataEntity.getStudentNumber() + "]");
                }
            }
        }
        return errorInfos;
    }

    private Map<String, Object> readTxtFile() throws IOException {
        Object contentObject = JsonPath.read(new File(rootPath + FileTypeEnum.TXT.name() + File.separator + txtFileName),
                "$");
        JSONArray contentJsonArray = JSONUtil.parseArray(contentObject);
        Map<String, Object> studentIdToObjectMap = new HashMap<>(contentJsonArray.size());
        for (Object object : contentJsonArray) {
            studentIdToObjectMap.put(JsonPath.read(object, "$.xh"), object);
        }
        return studentIdToObjectMap;
    }

    private List<ExcelDataEntity> readExcelFile(String sheetName) {
        String filePath = rootPath + FileTypeEnum.EXCEL.name() + File.separator + excelFileName;
        List<ExcelDataEntity> excelDataEntities = new ArrayList<>();
        EasyExcel.read(filePath, ExcelDataEntity.class, new PageReadListener<ExcelDataEntity>(excelDataEntities::addAll))
                .sheet(sheetName).doRead();
        return excelDataEntities;
    }

    @Override
    public void uploadFile(MultipartFile file, FileTypeEnum fileTypeEnum) throws IOException {
        if (fileTypeEnum == FileTypeEnum.EXCEL) {
            excelFileName = file.getOriginalFilename();
        }
        if (fileTypeEnum == FileTypeEnum.TXT) {
            txtFileName = file.getOriginalFilename();
        }
        Files.createDirectories(Paths.get(rootPath + fileTypeEnum.name()));
        Files.write(Paths.get(rootPath + fileTypeEnum.name() + "/", file.getOriginalFilename()), file.getBytes());
    }

    @Override
    public void clearFile() {
        FileUtil.clean(rootPath);
    }

    @Override
    public void deleteFile(String fileName) throws IOException {
        String extName = FileUtil.extName(fileName);
        Assert.notNull(extName, "文件格式有误");
        FileTypeEnum fileTypeEnum = FileTypeEnum.getFileTypeEnum(extName.toLowerCase());
        Assert.notNull(fileTypeEnum, "文件格式有误");
        Files.deleteIfExists(Paths.get(rootPath + fileTypeEnum.name() + File.separator + fileName));
    }
}
